package cc.rengu.igas.channel.cups.core.service.trans;

import cc.rengu.igas.channel.cups.common.constant.CupsConfigConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsParamConstant;
import cc.rengu.igas.channel.cups.common.constant.CupsTreeNodeConstant;
import cc.rengu.igas.channel.cups.common.enums.RespCodeEnum;
import cc.rengu.igas.channel.cups.core.model.CupsFieldBean;
import cc.rengu.igas.channel.cups.core.realize.CupsMacService;
import cc.rengu.igas.channel.cups.core.realize.impl.CupsMacServiceImpl;
import cc.rengu.igas.channel.cups.core.service.base.ManageService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.KeyInfoMapper;
import cc.rengu.oltp.service.common.dao.SecPlanInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.KeyInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SecPlanInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.DstChannelInfo;
import cc.rengu.oltp.service.common.entity.KeyInfo;
import cc.rengu.oltp.service.common.entity.SecPlanInfo;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.List;
import java.util.Optional;

/**
 * 银联发起重置cups密钥
 */
public class AcpCupsResetPinKeyService extends ManageService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        return null;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        BizResponse bizResponse = new BizResponse();
        String newEncPinKey = null;
        CupsFieldBean cupsFieldBean = new CupsFieldBean();
        ConvertUtil.convertOutput(cupsFieldBean);

        if (cupsFieldBean.getCupsField().getPrivAddData() != null) {
            newEncPinKey = cupsFieldBean.getCupsField().getPrivAddData().substring(4);
            rglog.debug("newEncPinKey=[{}]", newEncPinKey);
        } else {
            rglog.error("获取新密钥失败!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        /*获取主密钥信息*/
        KeyInfo lmkKeyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_LMK_KEY_INFO, KeyInfo.class);
        if (lmkKeyInfo == null) {
            rglog.error("获取机构主密钥失败!");
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }
        /*解密主密钥*/
        String pinKey = descyptKey(newEncPinKey, lmkKeyInfo);
        if (pinKey == null) {
            rglog.error("解密工作密钥失败!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        rglog.error("pinKey=[{}]", pinKey);
        KeyInfo macKeyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, KeyInfo.class);
        macKeyInfo.setKeyValue(pinKey);
        /*用新的pin密钥验证mac*/
        String macBlock = xmlTreeUtil.getXmlTreeStringValue(CupsTreeNodeConstant.CUPS_MAC_BLOCK);
        CupsMacService cupsMacService = new CupsMacServiceImpl();
        if (!cupsMacService.verifyReSetKeyMacString(macKeyInfo, cupsFieldBean.getCupsField().getMac(), macBlock)) {
            rglog.error("验证mac错误!");
            throw new BizException(RespCodeEnum.VERIFY_MAC_ERROR.getRespCode(), RespCodeEnum.VERIFY_MAC_ERROR.getRespDesc());
        }
        updatePinKeyInfo(pinKey);
        xmlTreeUtil.setXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_MAC_KEY_INFO, macKeyInfo);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {

    }

    private String descyptKey(String encKey, KeyInfo keyInfo) throws Exception {
        byte[] encData = ByteUtil.hexStringToByte(encKey);
        String encType = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ENC_TYPE);
        if ("0".equals(encType)) {
            rglog.debug("使用软加密,算法类型:<{}>,", keyInfo.getAlgorithmType());
            if ("3DES".equals(keyInfo.getAlgorithmType())) {
                /* return ByteUtil.bytesToHexString(DES3Util.decryptMode3DESDouble(ByteUtil.hexStringToByte(keyInfo.getKeyValue()),encData));*/
                return null;
            } else {
                byte[] keyValue = new byte[16];
                byte[] lmkKey = ByteUtil.hexStringToByte(keyInfo.getKeyValue());
                int iRet = SM4Util.sms4(encData, encData.length, lmkKey, keyValue, 0);
                if (iRet == 0) {
                    return ByteUtil.bytesToHexString(keyValue);
                } else {
                    return null;
                }
            }
        } else {
            /*硬加密，需要自己客户化*/
            return null;
        }
    }

    private void updatePinKeyInfo(String newPinKey) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        int iRetCode = 0;
        String algorithm = XmlConfigUtil.getXmlConfigCacheKeyValue(CupsConfigConstant.CUPS_CONF_NODE, CupsConfigConstant.CUPS_ALG_TYPE);
        KeyInfoMapper keyInfoMapper = new KeyInfoMapperImpl();
        KeyInfo pinKeyInfo = (KeyInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.CUPS_PIN_KEY_INFO, KeyInfo.class);
        if (pinKeyInfo == null) {
            pinKeyInfo = new KeyInfo();
            DstChannelInfo dstChannelInfo = (DstChannelInfo) xmlTreeUtil.getXmlTreeObjectValue(CupsTreeNodeConstant.DST_CHANNEL_INFO, DstChannelInfo.class);
            /* 根据通道安全计划获取安全计划 */
            SecPlanInfoMapper secPlanInfoMapper = new SecPlanInfoMapperImpl();
            List<SecPlanInfo> secPlanInfoList = secPlanInfoMapper.selectSecPlanInfoBySecPlanId(dstChannelInfo.getInstId(), dstChannelInfo.getSecPlanId());
            if (null != secPlanInfoList && !secPlanInfoList.isEmpty()) {
                xmlTreeUtil.setXmlTreeStringValue(CupsTreeNodeConstant.SEC_PLAN_INFO_LIST, JSON.toJSONString(secPlanInfoList));
                /*pin密钥*/
                Optional<SecPlanInfo> secPlanInfoOptPin = secPlanInfoList.stream().filter(item -> item.getSecPlanType().equals(CupsParamConstant.PIN_KEY_TYPE)).findFirst();
                if (secPlanInfoOptPin.isPresent()) {
                    pinKeyInfo.setKeyIndex(secPlanInfoOptPin.get().getSecPlanId() + secPlanInfoOptPin.get().getSecPlanType());
                }
            }
            pinKeyInfo.setAlgorithmType(algorithm);
            pinKeyInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyyddmmHHmmss"));
            pinKeyInfo.setKeyDesc("pin密钥");
            pinKeyInfo.setKeyStatus("1");
            pinKeyInfo.setKeyValue(newPinKey);
            iRetCode = keyInfoMapper.insertKeyInfo(pinKeyInfo);
        } else {
            pinKeyInfo.setKeyValue(newPinKey);
            pinKeyInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyyddmmHHmmss"));
            iRetCode = keyInfoMapper.updateKeyInfoByPrimaryKey(pinKeyInfo);
        }
        if (iRetCode != 0) {
            rglog.error("更新pinkey失败,iRetCode=[{}]", iRetCode);
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
    }
}
